home *** CD-ROM | disk | FTP | other *** search
/ The Guided Tour of Multimedia (Second Edition) / The Guided Tour of Multimedia (Second Edition).iso / trials / director / evalcopy / director.z / COMMPORT.C < prev    next >
C/C++ Source or Header  |  1994-06-02  |  30KB  |  1,003 lines

  1. /*****************************************************************************
  2.  
  3.                           Macromedia CommPort XObject
  4.                                        
  5.                          (c) Copyright 1993 Macromedia
  6.                               All Rights Reserved
  7.  
  8.  *****************************************************************************/
  9.  
  10. #include <windows.h>
  11. #include "XObject.h"
  12.  
  13. /*
  14. --------------------------------------------------------------------------
  15. Function Prototypes: 
  16. --------------------------------------------------------------------------
  17. */
  18.  
  19. short __far __pascal __export LibMain(
  20.     HANDLE hndInstance, WORD suDataSeg, WORD suHeapSize, LPBYTE pCmdLine);
  21. //DJ20jul93int _export _far _pascal WEP(int nParameter);
  22.  
  23. long __far __pascal __export _CommPort_mNew(
  24.     LxMemHandle hPortName, long lRecvBufSize, long lXmitBufSize, 
  25.     LxProcTablePtr xtbl, LxMemHandle hComm); 
  26. long __far __pascal __export _CommPort_mDispose(
  27.     LxProcTablePtr xtbl, LxMemHandle hComm); 
  28. LxMemHandle __far __pascal __export _CommPort_mName(
  29.     LxProcTablePtr xtbl, LxMemHandle hComm);
  30. LxMemHandle __far __pascal __export _CommPort_mPortName(
  31.     LxProcTablePtr xtbl, LxMemHandle hComm); 
  32. long __far __pascal __export _CommPort_mStatus(
  33.     LxProcTablePtr xtbl, LxMemHandle hComm);
  34. LxMemHandle __far __pascal __export _CommPort_mError(
  35.     long lErrorCode, LxProcTablePtr xtbl, LxMemHandle hComm); 
  36. long __far __pascal __export _CommPort_mSetup(
  37.     long lBaudRate, long lStopBits, long lParity, 
  38.     LxProcTablePtr xtbl, LxMemHandle hComm);
  39. long __far __pascal __export _CommPort_mSetBaudRate(
  40.     long lBaudRate, LxProcTablePtr xtbl, LxMemHandle hComm); 
  41. long __far __pascal __export _CommPort_mBaudRate(
  42.     LxProcTablePtr xtbl, LxMemHandle hComm); 
  43. long __far __pascal __export _CommPort_mSetDataBits(
  44.     long lDataBits, LxProcTablePtr xtbl, LxMemHandle hComm); 
  45. long __far __pascal __export _CommPort_mDataBits(
  46.     LxProcTablePtr xtbl, LxMemHandle hComm); 
  47. long __far __pascal __export _CommPort_mSetStopBits(
  48.     long lStopBits, LxProcTablePtr xtbl, LxMemHandle hComm); 
  49. long __far __pascal __export _CommPort_mStopBits(
  50.     LxProcTablePtr xtbl, LxMemHandle hComm);
  51. long __far __pascal __export _CommPort_mSetParity(
  52.     LxMemHandle hParity, LxProcTablePtr xtbl, LxMemHandle hComm); 
  53. LxMemHandle __far __pascal __export _CommPort_mParity(
  54.     LxProcTablePtr xtbl, LxMemHandle hComm); 
  55. long __far __pascal __export _CommPort_mSetFlowCtl(
  56.     LxMemHandle hFlow, LxProcTablePtr xtbl, LxMemHandle hComm); 
  57. LxMemHandle __far __pascal __export _CommPort_mFlowCtl(
  58.     LxProcTablePtr xtbl, LxMemHandle hComm); 
  59. long __far __pascal __export _CommPort_mWriteChar(
  60.     long lCharNum, LxProcTablePtr xtbl, LxMemHandle hComm); 
  61. long __far __pascal __export _CommPort_mWriteString(
  62.     LxMemHandle hData, LxProcTablePtr xtbl, LxMemHandle hComm); 
  63. long __far __pascal __export _CommPort_mWriteCount(
  64.     LxProcTablePtr xtbl, LxMemHandle hComm); 
  65. long __far __pascal __export _CommPort_mWriteFlush(
  66.     LxProcTablePtr xtbl, LxMemHandle hComm);
  67. long __far __pascal __export _CommPort_mReadChar(
  68.     LxProcTablePtr xtbl, LxMemHandle hComm); 
  69. LxMemHandle __far __pascal __export _CommPort_mReadString(
  70.     LxProcTablePtr xtbl, LxMemHandle hComm); 
  71. long __far __pascal __export _CommPort_mReadCount(
  72.     LxProcTablePtr xtbl, LxMemHandle hComm); 
  73. long __far __pascal __export _CommPort_mReadFlush(
  74.     LxProcTablePtr xtbl, LxMemHandle hComm); 
  75.  
  76.  
  77. /*
  78. --------------------------------------------------------------------------
  79. Constants: 
  80. --------------------------------------------------------------------------
  81. */
  82. #define COMMPORT_FLOW_XONXOFF   1
  83. #define COMMPORT_FLOW_HARDWARE  2
  84. #define COMMPORT_FLOW_NONE      3
  85.  
  86. #define COMM_SUCCESS            0
  87.  
  88. /*
  89. --------------------------------------------------------------------------
  90. Types: 
  91. --------------------------------------------------------------------------
  92. */
  93. typedef struct tagCommPort
  94. {
  95.     LxXObjHeader    head;           // Required header
  96.     short           sCommID;        // COM port ID
  97.     LxMemHandle     hPortName;      // COM port name (string handle)
  98.     char            bFlowCtl;       // COM port flow control setting
  99. }   CommPort, FAR * pCommPort;
  100.  
  101. /* 
  102. ------------------------------------------------------------------------
  103. Variables: 
  104. ------------------------------------------------------------------------
  105. */
  106. long lCommPortError = COMM_SUCCESS;
  107. HANDLE hInst;
  108.  
  109. /*
  110. ------------------------------------------------------------------------
  111. Macros:
  112. ------------------------------------------------------------------------
  113. */
  114.  
  115. /*
  116. ------------------------------------------------------------------------
  117. FUNCTION            ||      LibMain()
  118.  
  119. Windows Entry Procedure for DLLs.  Called by LibEntry routine. 
  120. ------------------------------------------------------------------------
  121. */
  122. short __far __pascal __export LibMain(
  123.     HANDLE hndInstance, WORD suDataSeg, WORD suHeapSize, LPBYTE pCmdLine)
  124. {
  125.     if (suHeapSize != 0)
  126.     {
  127.         if (! LocalInit( (UINT)suDataSeg, (UINT)NULL, (UINT)suHeapSize))
  128.         {
  129.             return (0);
  130.         }
  131.     }
  132.     hInst = hndInstance;
  133.     return (1);
  134. }
  135.  
  136. //DJ20jul93/*
  137. //DJ20jul93--------------------------------------------------------------------------
  138. //DJ20jul93FUNCTION            ||      WEP()
  139. //DJ20jul93
  140. //DJ20jul93Windows Exit Procedure for DLLs. 
  141. //DJ20jul93--------------------------------------------------------------------------
  142. //DJ20jul93*/
  143. //DJ20jul93int _export _far _pascal WEP(int nParameter)
  144. //DJ20jul93{
  145. //DJ20jul93    return 1;
  146. //DJ20jul93}
  147.  
  148. /*
  149. --------------------------------------------------------------------------
  150. FUNCTION            ||      _CommPort_mNew
  151.  
  152. Creates a new instance of a CommPort XObject.  Opens COM port and
  153. initializes instance variables.
  154. --------------------------------------------------------------------------
  155. */
  156. long __far __pascal __export _CommPort_mNew(
  157.     LxMemHandle hPortName, long lRecvBufSize, long lXmitBufSize, 
  158.     LxProcTablePtr xtbl, LxMemHandle hComm) 
  159. {
  160.     pCommPort   pComm;
  161.     LPSTR       pstrName;
  162.     DCB         dcb;
  163.  
  164.     lCommPortError = COMM_SUCCESS;
  165.     pstrName = xtbl->mem_Lock(hPortName);
  166.     if ((hComm = xtbl->mem_SetSize(hComm, (long)sizeof(CommPort))) != NULL)
  167.     {
  168.         pComm = xtbl->mem_Lock(hComm);
  169.         pComm->sCommID = OpenComm(pstrName, (WORD) lRecvBufSize,
  170.                                             (WORD) lXmitBufSize);
  171.         if (pComm->sCommID < 0)
  172.         {
  173.             lCommPortError = pComm->sCommID;
  174.         }
  175.         else
  176.         {
  177.             pComm->hPortName = xtbl->string_New(pstrName);
  178.  
  179.             // Initialize flow control to "None"
  180.             pComm->bFlowCtl = COMMPORT_FLOW_NONE;
  181.             dcb.fOutxCtsFlow = FALSE; 
  182.             dcb.fOutxDsrFlow = FALSE;
  183.             dcb.fOutX = FALSE;
  184.             dcb.fInX = FALSE;
  185.             dcb.fDtrflow = FALSE;
  186.             dcb.fRtsflow = FALSE;
  187.             if (SetCommState(&dcb) < 0)
  188.             {
  189.                 lCommPortError = GetCommError(pComm->sCommID, NULL);
  190.             }
  191.         }
  192.         xtbl->mem_Unlock(hComm);
  193.     }
  194.     else
  195.     {
  196.         lCommPortError = IE_MEMORY;
  197.     }
  198.     xtbl->mem_Unlock(hPortName);
  199.     return (lCommPortError);
  200. }
  201.  
  202. /*
  203. --------------------------------------------------------------------------
  204. FUNCTION       ||      _CommPort_mDispose
  205.  
  206. Dispose of XObject instance.
  207. --------------------------------------------------------------------------
  208. */
  209. long __far __pascal __export _CommPort_mDispose(
  210.     LxProcTablePtr xtbl, LxMemHandle hComm)
  211. {
  212.     pCommPort   pComm;
  213.  
  214.     lCommPortError = COMM_SUCCESS;
  215.     pComm = xtbl->mem_Lock(hComm);
  216.     if (CloseComm(pComm->sCommID) <= 0)
  217.     {
  218.         /* don't know what error code to use here */
  219.     }
  220.     if (pComm->hPortName != NULL)
  221.     {
  222.         xtbl->mem_Dispose(pComm->hPortName);
  223.     }
  224.     xtbl->mem_Unlock(hComm);
  225.     xtbl->xobj_Dispose(hComm);
  226.     return (lCommPortError);
  227. }
  228.  
  229. /*
  230. --------------------------------------------------------------------------
  231. FUNCTION       ||      _CommPort_mName
  232.  
  233. Returns name of XObject (e.g. "CommPort")
  234. --------------------------------------------------------------------------
  235. */
  236. LxMemHandle __far __pascal __export _CommPort_mName(
  237.     LxProcTablePtr xtbl, LxMemHandle hComm)
  238. {
  239.     lCommPortError = COMM_SUCCESS;
  240.     return (xtbl->string_New("CommPort"));
  241. }
  242.  
  243. /*
  244. --------------------------------------------------------------------------
  245. FUNCTION            ||      _CommPort_mPortName
  246.  
  247. Returns name of opened COM port (e.g., "COM1")
  248. --------------------------------------------------------------------------
  249. */
  250. LxMemHandle __far __pascal __export _CommPort_mPortName(
  251.     LxProcTablePtr xtbl, LxMemHandle hComm)
  252. {
  253.     pCommPort   pComm;
  254.     LxMemHandle hName;
  255.  
  256.     lCommPortError = COMM_SUCCESS;
  257.     pComm = xtbl->mem_Lock(hComm);
  258.     hName = xtbl->mem_Clone(pComm->hPortName);
  259.     xtbl->mem_Unlock(hComm);
  260.     return (hName);
  261. }
  262.  
  263. /*
  264. --------------------------------------------------------------------------
  265. FUNCTION        ||      _CommPort_mStatus 
  266.  
  267. Returns numberic status of last method call.
  268. --------------------------------------------------------------------------
  269. */
  270. long __far __pascal __export _CommPort_mStatus(
  271.     LxProcTablePtr xtbl, LxMemHandle hComm)
  272. {
  273.     return (lCommPortError);
  274. }
  275.  
  276. /*
  277. --------------------------------------------------------------------------
  278. FUNCTION        ||      _CommPort_mError 
  279.  
  280. Returns error string, given error code (from mStatus method).
  281. --------------------------------------------------------------------------
  282. */
  283. LxMemHandle __far __pascal __export _CommPort_mError(
  284.     long lErrorCode, LxProcTablePtr xtbl, LxMemHandle hComm)
  285. {
  286.     LPSTR       pstrMsg;
  287.  
  288.     switch ((short) lErrorCode)
  289.     {
  290.         case COMM_SUCCESS:
  291.             pstrMsg = "";
  292.             break;
  293.         case CE_RXOVER:
  294.             pstrMsg = "Receive Queue overflow"; 
  295.             break;
  296.         case CE_OVERRUN:
  297.             pstrMsg = "Receive Overrun Error"; 
  298.             break;
  299.         case CE_RXPARITY:
  300.             pstrMsg = "Receive Parity Error"; 
  301.             break;
  302.         case CE_FRAME:
  303.             pstrMsg = "Receive Framing error"; 
  304.             break;
  305.         case CE_BREAK:
  306.             pstrMsg = "Break Detected";
  307.             break;
  308.         case CE_CTSTO:
  309.             pstrMsg = "CTS Timeout";
  310.             break;
  311.         case CE_DSRTO:
  312.             pstrMsg = "DSR Timeout";
  313.             break;
  314.         case CE_RLSDTO:
  315.             pstrMsg = "RLSD Timeout";
  316.             break;
  317.         case CE_TXFULL:
  318.             pstrMsg = "TX Queue is full";
  319.             break;
  320.         case CE_PTO:
  321.             pstrMsg = "LPTx Timeout";
  322.             break;
  323.         case CE_IOE:
  324.             pstrMsg = "LPTx I/O Error";
  325.             break;
  326.         case CE_DNS:
  327.             pstrMsg = "LPTx Device not selected";
  328.             break;
  329.         case CE_OOP:
  330.             pstrMsg = "LPTx Out-Of-Paper";
  331.             break;
  332.         case CE_MODE:
  333.             pstrMsg = "Requested mode unsupported";
  334.             break;
  335.         case IE_BADID:
  336.             pstrMsg = "Invalid or unsupported id";
  337.             break;
  338.         case IE_OPEN:
  339.             pstrMsg = "Device Already Open";
  340.             break;
  341.         case IE_NOPEN:
  342.             pstrMsg = "Device Not Open";
  343.             break;
  344.         case IE_MEMORY:
  345.             pstrMsg = "Unable to allocate memory";
  346.             break;
  347.         case IE_DEFAULT:
  348.             pstrMsg = "Error in default parameters";
  349.             break;
  350.         case IE_HARDWARE:
  351.             pstrMsg = "Hardware Not Present";
  352.             break;
  353.         case IE_BYTESIZE:
  354.             pstrMsg = "Illegal Byte Size";
  355.             break;
  356.         case IE_BAUDRATE:
  357.             pstrMsg = "Unsupported BaudRate";
  358.             break;
  359.         default:
  360.             pstrMsg = "Unknown error";
  361.             break;
  362.     }
  363.     return (xtbl->string_New(pstrMsg));
  364. }
  365.  
  366. /*
  367. --------------------------------------------------------------------------
  368. FUNCTION        ||      _CommPort_mSetup
  369.  
  370. Sets the COM port baud rate, stop bits, and parity.  Compatible with
  371. Mac SerialPort XObject calling conventions.
  372. --------------------------------------------------------------------------
  373. */
  374. long __far __pascal __export _CommPort_mSetup(
  375.     long lBaudRate, long lStopBits, long lParity, 
  376.     LxProcTablePtr xtbl, LxMemHandle hComm)
  377. {
  378.     pCommPort   pComm;
  379.     DCB         dcb;
  380.  
  381.     lCommPortError = COMM_SUCCESS;
  382.     pComm = xtbl->mem_Lock(hComm);
  383.     GetCommState(pComm->sCommID, &dcb);
  384.  
  385.     dcb.BaudRate = (WORD) lBaudRate;
  386.     dcb.ByteSize = 8;
  387.  
  388.     // Set Stop Bits:
  389.     if (lStopBits == 10)
  390.     {
  391.         dcb.StopBits = ONESTOPBIT;
  392.     }
  393.     else if (lStopBits == 15)
  394.     {
  395.         dcb.StopBits = ONE5STOPBITS;
  396.     }
  397.     else if (lStopBits == 20)
  398.     {
  399.         dcb.StopBits = TWOSTOPBITS;
  400.     }
  401.  
  402.     // Set Parity Value:
  403.     if (lParity == 0)
  404.     {
  405.         dcb.Parity = NOPARITY;
  406.     }
  407.     else if (lParity == 1)
  408.     {
  409.         dcb.Parity = ODDPARITY;
  410.     }
  411.     else if (lParity == 2)
  412.     {
  413.         dcb.Parity = EVENPARITY;
  414.     }
  415.  
  416.  
  417.     if (SetCommState(&dcb) < 0)
  418.     {
  419.         lCommPortError = GetCommError(pComm->sCommID, NULL);
  420.     }
  421.     xtbl->mem_Unlock(hComm);
  422.     return (lCommPortError);
  423. }
  424.  
  425. /*
  426. --------------------------------------------------------------------------
  427. FUNCTION        ||      _CommPort_mSetBaudRate 
  428.  
  429. Sets the COM port baud rate.
  430. --------------------------------------------------------------------------
  431. */
  432. long __far __pascal __export _CommPort_mSetBaudRate(
  433.     long lBaudRate, LxProcTablePtr xtbl, LxMemHandle hComm)
  434. {
  435.     pCommPort   pComm;
  436.     DCB         dcb;
  437.  
  438.     lCommPortError = COMM_SUCCESS;
  439.     pComm = xtbl->mem_Lock(hComm);
  440.     GetCommState(pComm->sCommID, &dcb);
  441.     dcb.BaudRate = (WORD) lBaudRate;
  442.     if (SetCommState(&dcb) < 0)
  443.     {
  444.         lCommPortError = GetCommError(pComm->sCommID, NULL);
  445.     }
  446.     xtbl->mem_Unlock(hComm);
  447.     return (lCommPortError);
  448. }
  449.  
  450. /*
  451. --------------------------------------------------------------------------
  452. FUNCTION        ||      _CommPort_mBaudRate 
  453.  
  454. Returns the COM ports baud rate.
  455. --------------------------------------------------------------------------
  456. */
  457. long __far __pascal __export _CommPort_mBaudRate(
  458.     LxProcTablePtr xtbl, LxMemHandle hComm)
  459. {
  460.     pCommPort   pComm;
  461.     long        lBaudRate;
  462.     DCB         dcb;
  463.  
  464.     lCommPortError = COMM_SUCCESS;
  465.     pComm = xtbl->mem_Lock(hComm);
  466.     GetCommState(pComm->sCommID, &dcb);
  467.     lBaudRate = dcb.BaudRate;
  468.     xtbl->mem_Unlock(hComm);
  469.     return (lBaudRate);
  470. }
  471.  
  472. /*
  473. --------------------------------------------------------------------------
  474. FUNCTION        ||      _CommPort_mSetDataBits 
  475.  
  476. Sets the number of data bits (in lDataBits):
  477. --------------------------------------------------------------------------
  478. */
  479. long __far __pascal __export _CommPort_mSetDataBits(
  480.     long lDataBits, LxProcTablePtr xtbl, LxMemHandle hComm)
  481. {
  482.     pCommPort pComm;
  483.     DCB     dcb;
  484.  
  485.     lCommPortError = COMM_SUCCESS;
  486.     pComm = xtbl->mem_Lock(hComm);
  487.     GetCommState(pComm->sCommID, &dcb);
  488.     dcb.ByteSize = (BYTE) lDataBits;
  489.     if (SetCommState(&dcb) < 0)
  490.     {
  491.         lCommPortError = GetCommError(pComm->sCommID, NULL);
  492.     }
  493.     xtbl->mem_Unlock(hComm);
  494.     return (lCommPortError);
  495. }
  496.  
  497. /*
  498. --------------------------------------------------------------------------
  499. FUNCTION        ||      _CommPort_mDataBits 
  500.  
  501. Returns the number of data bits.
  502. --------------------------------------------------------------------------
  503. */
  504.  
  505. long __far __pascal __export _CommPort_mDataBits(
  506.     LxProcTablePtr xtbl, LxMemHandle hComm)
  507. {
  508.     pCommPort   pComm;
  509.     long        lDataBits;
  510.     DCB         dcb;
  511.  
  512.     lCommPortError = COMM_SUCCESS;
  513.     pComm = xtbl->mem_Lock(hComm);
  514.     GetCommState(pComm->sCommID, &dcb);
  515.     lDataBits = dcb.ByteSize;
  516.     xtbl->mem_Unlock(hComm);
  517.     return (lDataBits);
  518. }
  519.  
  520. /*
  521. --------------------------------------------------------------------------
  522. FUNCTION        ||      _CommPort_mSetStopBits 
  523.  
  524. Sets the number of stop bits (in lStopBits):
  525.     10 -> 1 Stop bits
  526.     15 -> 1.5 Stop bits
  527.     20 -> 2 Stop bits
  528. --------------------------------------------------------------------------
  529. */
  530. long __far __pascal __export _CommPort_mSetStopBits(
  531.     long lStopBits, LxProcTablePtr xtbl, LxMemHandle hComm)
  532. {
  533.     pCommPort   pComm;
  534.     DCB         dcb;
  535.  
  536.     lCommPortError = COMM_SUCCESS;
  537.     pComm = xtbl->mem_Lock(hComm);
  538.     GetCommState(pComm->sCommID, &dcb);
  539.     if (lStopBits == 10)
  540.     {
  541.         dcb.StopBits = ONESTOPBIT;
  542.     }
  543.     else if (lStopBits == 15)
  544.     {
  545.         dcb.StopBits = ONE5STOPBITS;
  546.     }
  547.     else if (lStopBits == 20)
  548.     {
  549.         dcb.StopBits = TWOSTOPBITS;
  550.     }
  551.     if (SetCommState(&dcb) < 0)
  552.     {
  553.         lCommPortError = GetCommError(pComm->sCommID, NULL);
  554.     }
  555.     xtbl->mem_Unlock(hComm);
  556.     return (lCommPortError);
  557. }
  558.  
  559. /*
  560. --------------------------------------------------------------------------
  561. FUNCTION        ||      _CommPort_mStopBits 
  562.  
  563. Returns the number of stop bits.  (See mSetStopBits for definition of
  564. return values.)
  565. --------------------------------------------------------------------------
  566. */
  567. long __far __pascal __export _CommPort_mStopBits(
  568.     LxProcTablePtr xtbl, LxMemHandle hComm)
  569. {
  570.     pCommPort   pComm;
  571.     long        lStopBits;
  572.     DCB         dcb;
  573.  
  574.     lCommPortError = COMM_SUCCESS;
  575.     pComm = xtbl->mem_Lock(hComm);
  576.     GetCommState(pComm->sCommID, &dcb);
  577.     if (dcb.StopBits == ONESTOPBIT)
  578.     {
  579.         lStopBits = 10;
  580.     }
  581.     else if (dcb.StopBits == ONE5STOPBITS)
  582.     {
  583.         lStopBits = 15;
  584.     }
  585.     else if (dcb.StopBits == TWOSTOPBITS)
  586.     {
  587.         lStopBits = 20;
  588.     }
  589.     else
  590.     {
  591.         lStopBits = 0;
  592.     }
  593.     xtbl->mem_Unlock(hComm);
  594.     return (lStopBits);
  595. }
  596.  
  597. /*
  598. --------------------------------------------------------------------------
  599. FUNCTION        ||      _CommPort_mSetParity 
  600.  
  601. Sets the COM port parity (in string hParity):
  602.     "Odd"       Sets odd parity
  603.     "Even"      Sets even parity
  604.     "Mark"      Sets mark parity
  605.     "Space"     Sets space parity
  606.     "None"      Sets no parity 
  607. --------------------------------------------------------------------------
  608. */
  609. long __far __pascal __export _CommPort_mSetParity(
  610.     LxMemHandle hParity, LxProcTablePtr xtbl, LxMemHandle hComm)
  611. {
  612.     pCommPort   pComm;
  613.     LPSTR       pstrParity;
  614.     DCB         dcb;
  615.  
  616.     lCommPortError = COMM_SUCCESS;
  617.     pComm = xtbl->mem_Lock(hComm);
  618.     pstrParity = xtbl->mem_Lock(hParity);
  619.     GetCommState(pComm->sCommID, &dcb);
  620.     if (lstrcmpi(pstrParity, "Even") == 0)
  621.     {
  622.         dcb.Parity = EVENPARITY;
  623.     }
  624.     else if (lstrcmpi(pstrParity, "Odd") == 0)
  625.     {
  626.         dcb.Parity = ODDPARITY;
  627.     }
  628.     else if (lstrcmpi(pstrParity, "Mark") == 0)
  629.     {
  630.         dcb.Parity = MARKPARITY;
  631.     }
  632.     else if (lstrcmpi(pstrParity, "Space") == 0) {
  633.         dcb.Parity = SPACEPARITY;
  634.     }
  635.     else if (lstrcmpi(pstrParity, "None") == 0)
  636.     {
  637.         dcb.Parity = NOPARITY;
  638.     }
  639.     if (SetCommState(&dcb) < 0)
  640.     {
  641.         lCommPortError = GetCommError(pComm->sCommID, NULL);
  642.     }
  643.     xtbl->mem_Unlock(hParity);
  644.     xtbl->mem_Unlock(hComm);
  645.     return (lCommPortError);
  646. }
  647.  
  648. /*
  649. --------------------------------------------------------------------------
  650. FUNCTION        ||      _CommPort_mParity 
  651.  
  652. Returns the current COM port parity (as a string).  See mSetParity for
  653. possible return values.
  654. --------------------------------------------------------------------------
  655. */
  656. LxMemHandle __far __pascal __export _CommPort_mParity(
  657.     LxProcTablePtr xtbl, LxMemHandle hComm)
  658. {
  659.     pCommPort   pComm;
  660.     LPSTR       pstrParity;
  661.     DCB         dcb;
  662.  
  663.     lCommPortError = COMM_SUCCESS;
  664.     pComm = xtbl->mem_Lock(hComm);
  665.     GetCommState(pComm->sCommID, &dcb);
  666.     if (dcb.Parity == EVENPARITY)
  667.     {
  668.         pstrParity = "Even";
  669.     }
  670.     else if (dcb.Parity == ODDPARITY)
  671.     {
  672.         pstrParity = "Odd";
  673.     }
  674.     else if (dcb.Parity == MARKPARITY)
  675.     {
  676.         pstrParity = "Mark";
  677.     }
  678.     else if (dcb.Parity == SPACEPARITY)
  679.     {
  680.         pstrParity = "Space";
  681.     }
  682.     else if (dcb.Parity == NOPARITY)
  683.     {
  684.         pstrParity = "None";
  685.     }
  686.     else
  687.     {
  688.         pstrParity = "";
  689.     }
  690.     xtbl->mem_Unlock(hComm);
  691.     return (xtbl->string_New(pstrParity));
  692. }
  693.  
  694. /*
  695. --------------------------------------------------------------------------
  696. FUNCTION        ||      _CommPort_mSetFlowCtl 
  697.  
  698. Set flow control for COM Port (in string hFlow):
  699.     "XonXoff"   Sets xon/xoff protocal
  700.     "Hardware"  Sets CTS/RTS hardware protocal
  701.     "None"      Sets no flow control
  702. --------------------------------------------------------------------------
  703. */
  704. long __far __pascal __export _CommPort_mSetFlowCtl(
  705.     LxMemHandle hFlow, LxProcTablePtr xtbl, LxMemHandle hComm)
  706. {
  707.     pCommPort   pComm;
  708.     LPSTR       pstrFlow;
  709.     DCB         dcb;
  710.  
  711.     lCommPortError = COMM_SUCCESS;
  712.     pComm = xtbl->mem_Lock(hComm); 
  713.     pstrFlow = xtbl->mem_Lock(hFlow);
  714.     GetCommState(pComm->sCommID, &dcb);
  715.  
  716.     if (lstrcmpi(pstrFlow, "XonXoff") == 0) 
  717.     {
  718.         pComm->bFlowCtl = COMMPORT_FLOW_XONXOFF;
  719.         dcb.fOutxCtsFlow = FALSE; 
  720.         dcb.fOutxDsrFlow = FALSE;
  721.         dcb.fOutX = TRUE;
  722.         dcb.fInX = TRUE;
  723.         dcb.fDtrflow = FALSE;
  724.         dcb.fRtsflow = FALSE;
  725.     }
  726.     else if (lstrcmpi(pstrFlow, "Hardware") == 0) 
  727.     {
  728.         pComm->bFlowCtl = COMMPORT_FLOW_HARDWARE;
  729.         dcb.fOutxCtsFlow = TRUE; 
  730.         dcb.fOutxDsrFlow = TRUE;
  731.         dcb.fOutX = FALSE;
  732.         dcb.fInX = FALSE;
  733.         dcb.fDtrflow = TRUE;
  734.         dcb.fRtsflow = TRUE;
  735.     }
  736.     else if (lstrcmpi(pstrFlow, "None") == 0) 
  737.     {
  738.         pComm->bFlowCtl = COMMPORT_FLOW_NONE;
  739.         dcb.fOutxCtsFlow = FALSE; 
  740.         dcb.fOutxDsrFlow = FALSE;
  741.         dcb.fOutX = FALSE;
  742.         dcb.fInX = FALSE;
  743.         dcb.fDtrflow = FALSE;
  744.         dcb.fRtsflow = FALSE;
  745.     }
  746.     if (SetCommState(&dcb) < 0)
  747.     {
  748.         lCommPortError = GetCommError(pComm->sCommID, NULL);
  749.     }
  750.     xtbl->mem_Unlock(hFlow);
  751.     xtbl->mem_Unlock(hComm);
  752.     return (lCommPortError);
  753. }
  754.  
  755. /*
  756. --------------------------------------------------------------------------
  757. FUNCTION        ||      _CommPort_mFlowCtl
  758.  
  759. Returns (as a string) the current flow control setting.  See mSetFlowCtl
  760. for possible return values.
  761. --------------------------------------------------------------------------
  762. */
  763. LxMemHandle __far __pascal __export _CommPort_mFlowCtl(
  764.     LxProcTablePtr xtbl, LxMemHandle hComm)
  765. {
  766.     pCommPort   pComm;
  767.     LPSTR       pstrFlow;
  768.     DCB         dcb;
  769.     lCommPortError = COMM_SUCCESS;
  770.     pComm = xtbl->mem_Lock(hComm);
  771.     GetCommState(pComm->sCommID, &dcb);
  772.     if (pComm->bFlowCtl == COMMPORT_FLOW_XONXOFF)
  773.     {
  774.         pstrFlow = "XonXoff";
  775.     }
  776.     else if (pComm->bFlowCtl == COMMPORT_FLOW_HARDWARE)
  777.     {
  778.         pstrFlow = "Hardware";
  779.     }
  780.     else if (pComm->bFlowCtl == COMMPORT_FLOW_NONE)
  781.     {
  782.         pstrFlow = "None";
  783.     }
  784.     else
  785.     {
  786.         pstrFlow = "";
  787.     }
  788.     xtbl->mem_Unlock(hComm);
  789.     return (xtbl->string_New(pstrFlow));
  790. }
  791.  
  792. /*
  793. --------------------------------------------------------------------------
  794. FUNCTION        ||      _CommPort_mWriteChar
  795.  
  796. Write a single character (given as an ASCII code value) to the COM port.
  797. --------------------------------------------------------------------------
  798. */
  799. long __far __pascal __export _CommPort_mWriteChar(
  800.     long lCharNum, LxProcTablePtr xtbl, LxMemHandle hComm)
  801. {
  802.     pCommPort   pComm;
  803.     BYTE        strChar;
  804.  
  805.     pComm = xtbl->mem_Lock(hComm);
  806.     strChar = (BYTE) lCharNum;
  807.     if (WriteComm(pComm->sCommID, &strChar, 1) != 1)
  808.     {
  809.         lCommPortError = GetCommError(pComm->sCommID, NULL);
  810.     }
  811.     xtbl->mem_Unlock(hComm);
  812.     return (lCommPortError);
  813. }
  814.  
  815. /*
  816. --------------------------------------------------------------------------
  817. FUNCTION        ||      _CommPort_mWriteString
  818.  
  819. Write a null-terminated string to the COM port.
  820. --------------------------------------------------------------------------
  821. */
  822. long __far __pascal __export _CommPort_mWriteString(
  823.     LxMemHandle hData, LxProcTablePtr xtbl, LxMemHandle hComm)
  824. {
  825.     pCommPort   pComm;
  826.     short       sLen;
  827.     LPSTR       pstrData;
  828.  
  829.     lCommPortError = COMM_SUCCESS;
  830.     pComm = xtbl->mem_Lock(hComm);
  831.     pstrData = xtbl->mem_Lock(hData); 
  832.     sLen = lstrlen(pstrData);
  833.  
  834.     if (WriteComm(pComm->sCommID, pstrData, sLen) != sLen)
  835.     {
  836.         lCommPortError = GetCommError(pComm->sCommID, NULL);
  837.     }
  838.     xtbl->mem_Unlock(hData);
  839.     xtbl->mem_Unlock(hComm);
  840.     return (lCommPortError);
  841. }
  842.  
  843. /*
  844. --------------------------------------------------------------------------
  845. FUNCTION   ||      _CommPort_mWriteCount
  846.  
  847. Return the pending write count for the last transmission.
  848. --------------------------------------------------------------------------
  849. */
  850. long __far __pascal __export _CommPort_mWriteCount(
  851.     LxProcTablePtr xtbl, LxMemHandle hComm)
  852. {
  853.     pCommPort   pComm;
  854.     long        lCount;
  855.     COMSTAT     stat;
  856.  
  857.     lCommPortError = COMM_SUCCESS;
  858.     pComm = xtbl->mem_Lock(hComm);
  859.     GetCommError(pComm->sCommID, &stat);
  860.     lCount = stat.cbOutQue;
  861.     xtbl->mem_Unlock(hComm);
  862.     return (lCount);
  863. }
  864.  
  865. /*
  866. --------------------------------------------------------------------------
  867. FUNCTION   ||      _CommPort_mWriteFlush
  868.  
  869. Flush any pending writes to the COM port.
  870. --------------------------------------------------------------------------
  871. */
  872. long __far __pascal __export _CommPort_mWriteFlush(
  873.     LxProcTablePtr xtbl, LxMemHandle hComm)
  874. {
  875.     pCommPort   pComm;
  876.  
  877.     lCommPortError = COMM_SUCCESS;
  878.     pComm = xtbl->mem_Lock(hComm);
  879.     FlushComm(pComm->sCommID, 0);       /* 0 = transmit buffer */
  880.     xtbl->mem_Unlock(hComm);
  881.     return (lCommPortError);
  882. }
  883.  
  884. /*
  885. --------------------------------------------------------------------------
  886. FUNCTION   ||      _CommPort_mReadChar
  887.  
  888. Read and return a single character (as an ASCII code value) from the COM port.
  889. --------------------------------------------------------------------------
  890. */
  891. long __far __pascal __export _CommPort_mReadChar(
  892.     LxProcTablePtr xtbl, LxMemHandle hComm)
  893. {
  894.     pCommPort   pComm;
  895.     BYTE        strChar;
  896.     long        lCharNum;
  897.  
  898.     lCommPortError = COMM_SUCCESS;
  899.     pComm = xtbl->mem_Lock(hComm);
  900.     if (ReadComm(pComm->sCommID, &strChar, 1) <= 0)
  901.     {
  902.         /* zero count from ReadComm may or may not be an error */
  903.         lCommPortError = GetCommError(pComm->sCommID, NULL);
  904.     }
  905.     if (lCommPortError == COMM_SUCCESS)
  906.     {
  907.         lCharNum = strChar;
  908.     }
  909.     else
  910.     {
  911.         lCharNum = -1;
  912.     }
  913.     xtbl->mem_Unlock(hComm);
  914.     return (lCharNum);
  915. }
  916.  
  917. /*
  918. --------------------------------------------------------------------------
  919. FUNCTION                ||      _CommPort_mReadString
  920.  
  921. Read and return a null-terminated string from the COM port.
  922. --------------------------------------------------------------------------
  923. */
  924. LxMemHandle __far __pascal __export _CommPort_mReadString(
  925.     LxProcTablePtr xtbl, LxMemHandle hComm)
  926. {
  927.     pCommPort   pComm;
  928.     COMSTAT     stat;
  929.     short       sLen;
  930.     LxMemHandle hData;
  931.     LPSTR       pbData;
  932.  
  933.     lCommPortError = COMM_SUCCESS;
  934.     pComm = xtbl->mem_Lock(hComm);
  935.     GetCommError(pComm->sCommID, &stat);
  936.     sLen = stat.cbInQue;
  937.     if (sLen == 0)
  938.     {
  939.         hData = xtbl->mem_New(1, TRUE);
  940.     }
  941.     else
  942.     {
  943.         /* should be able to read at least sLen bytes */
  944.         hData = xtbl->mem_New((long)sLen + 1, TRUE);
  945.         if (hData != NULL)
  946.         {
  947.             pbData = xtbl->mem_Lock(hData);
  948.             if (ReadComm(pComm->sCommID, pbData, sLen) != sLen)
  949.             {
  950.                 lCommPortError = GetCommError(pComm->sCommID, NULL);
  951.             }
  952.             xtbl->mem_Unlock(hData);/* was cleared to NULL when allocated */
  953.         }
  954.         else
  955.         {
  956.             lCommPortError = IE_MEMORY;
  957.         }
  958.     }
  959.     xtbl->mem_Unlock(hComm);
  960.     return (hData);
  961. }
  962.  
  963. /*
  964. --------------------------------------------------------------------------
  965. FUNCTION   ||      _CommPort_mReadCount
  966.  
  967. Return a count of characters pending a read operation.
  968. --------------------------------------------------------------------------
  969. */
  970. long __far __pascal __export _CommPort_mReadCount(
  971.     LxProcTablePtr xtbl, LxMemHandle hComm)
  972. {
  973.     pCommPort   pComm;
  974.     long        lCount;
  975.     COMSTAT     stat;
  976.  
  977.     lCommPortError = COMM_SUCCESS;
  978.     pComm = xtbl->mem_Lock(hComm);
  979.     GetCommError(pComm->sCommID, &stat);
  980.     lCount = stat.cbInQue;
  981.     xtbl->mem_Unlock(hComm);
  982.     return (lCount);
  983. }
  984.  
  985. /*
  986. --------------------------------------------------------------------------
  987. FUNCTION   ||      _CommPort_mReadFlush
  988.  
  989. Flush any pending input from the COM port.
  990. --------------------------------------------------------------------------
  991. */
  992. long __far __pascal __export _CommPort_mReadFlush(
  993.     LxProcTablePtr xtbl, LxMemHandle hComm)
  994. {
  995.     pCommPort   pComm;
  996.  
  997.     lCommPortError = COMM_SUCCESS;
  998.     pComm = xtbl->mem_Lock(hComm);
  999.     FlushComm(pComm->sCommID, 1);       /* 1 = receive buffer */
  1000.     xtbl->mem_Unlock(hComm);
  1001.     return (lCommPortError);
  1002. }
  1003.